package com.luyun.frogpay.view.home;


import android.content.Context;
import android.os.RemoteException;

import com.blankj.utilcode.util.ToastUtils;
import com.geekmaker.paykeyboard.DefaultKeyboardListener;
import com.geekmaker.paykeyboard.IPayRequest;
import com.luyun.frogpay.base.baseclass.BaseObserver;
import com.luyun.frogpay.base.baseclass.BasePresenter;
import com.luyun.frogpay.base.baseclass.BaseResponse;
import com.luyun.frogpay.base.global.Constants;
import com.luyun.frogpay.base.global.EnumFaceAuthType;
import com.luyun.frogpay.base.global.EnumWxFacePayPublicErrorCode;
import com.luyun.frogpay.base.global.SPKey;
import com.luyun.frogpay.base.utils.Log;
import com.luyun.frogpay.base.utils.MD5Utils;
import com.luyun.frogpay.base.utils.RandomStringUtil;
import com.luyun.frogpay.keyboard.jingu.PayKeyboard;
import com.luyun.frogpay.pojo.KqwSpeechCompound;
import com.luyun.frogpay.pojo.event.EventKeyboardInfo;
import com.luyun.frogpay.pojo.request.RequestBase;
import com.luyun.frogpay.pojo.response.AuthInfoRsp;
import com.luyun.frogpay.pojo.response.CodePayRsp;
import com.luyun.frogpay.pojo.response.FacePayRsp;
import com.luyun.frogpay.pojo.response.LoginRsp;
import com.luyun.frogpay.keyboard.jingu.ZhsPayKeyboard;
import com.orhanobut.hawk.Hawk;
import com.tencent.wxpayface.IWxPayfaceCallback;
import com.tencent.wxpayface.WxPayFace;

import org.greenrobot.eventbus.EventBus;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.inject.Inject;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Function;

import static com.luyun.frogpay.base.global.WxPayFaceSDKParam.RAWDATA;
import static com.luyun.frogpay.base.global.WxPayFaceSDKParam.RETURN_CODE;
import static com.luyun.frogpay.base.global.WxPayFaceSDKParam.RETURN_MSG;

public class HomePresenter extends BasePresenter<HomeContract.IHomeView> implements HomeContract.IHomePresenter {

    @Inject
    HomeModel homeModel;
    /**
     * 物理小键盘
     */
    private PayKeyboard keyboard;

    /**
     * 开启小键盘心跳服务
     */
    private ScheduledExecutorService heartService = Executors.newScheduledThreadPool(1);

    public static final int IDLE = 932;
    public static final int CODE_SCANING = 480;
    public static final int FACE_SCANING = 652;
    public int currentStatus = IDLE;



    Context context;

    @Inject
    public HomePresenter() {
    }

    @Override
    public void getWxfacepayRawdata() {
        view.setCurrentStatus(HomeActivity.IDLE);
        WxPayFace.getInstance().getWxpayfaceRawdata(new IWxPayfaceCallback() {
            @Override
            public void response(Map map) throws RemoteException {
                Log.d("getWxpayfaceRawdata: " + map.toString());
                if (null == map) {
                    return;
                }
                String code = (String) map.get(RETURN_CODE);
                String msg = (String) map.get(RETURN_MSG);
                String rawdata = map.get(RAWDATA).toString();
                if (code == null || rawdata == null || !code.equals(EnumWxFacePayPublicErrorCode.SUCCESS.toString())) {
                    new RuntimeException("调用返回非成功信息,return_msg:" + msg + "   ").printStackTrace();
                    return;
                }
                getAuthInfo(rawdata);
            }
        });
    }

    @Override
    public void getAuthInfo(String rawdata) {
        LoginRsp loginRsp = Hawk.get(SPKey.LOGIN_RSP);
        int sotreId = loginRsp.getSid();
        String nonceStr = RandomStringUtil.getRandomString(10);
        Map<String, Object> map = new HashMap<>();
        map.put("store_id", sotreId);
        map.put("rawdata", rawdata);
        map.put("nonce_str", nonceStr);
        String dataAddSaleStr = buildRequestDataForSign(map, loginRsp.getKey());
        String sign = MD5Utils.MD5Upper(dataAddSaleStr);
        RequestBase requestBase = new RequestBase(loginRsp.getAppid(), Constants.WX_FACEAUTHINFO, map, sign);

        homeModel.getAuthInfo(requestBase)
                .subscribe(new BaseObserver<AuthInfoRsp>() {

                    @Override
                    protected void onSuccees(BaseResponse<AuthInfoRsp> t) throws Exception {
                        getWxPayFaceCode(t.getData());
//                        getWxpayfaceUserInfo(t.getData());
                    }

                    @Override
                    protected void onCodeError(BaseResponse<AuthInfoRsp> t) throws Exception {
                        ToastUtils.showShort(t.getMsg());
                    }

                    @Override
                    protected void onFailure(String errorMsg, boolean isNetWorkError) throws Exception {
                        ToastUtils.showShort(errorMsg);
                    }
                });
    }

    @Override
    public void getWxPayFaceCode(AuthInfoRsp authInfoRsp) {
        currentStatus = FACE_SCANING;
        Map<String, Object> map = new HashMap<>();
        map.put("appid", authInfoRsp.getAppid());
        map.put("mch_id", authInfoRsp.getMch_id());
        map.put("store_id", authInfoRsp.getStore_id());
        map.put("out_trade_no", authInfoRsp.getOut_trade_no());
        map.put("total_fee", "1");
        map.put("face_authtype", EnumFaceAuthType.FACEPAY.toString());
        map.put("authinfo", authInfoRsp.getAuth_info());
        map.put("ask_face_permit", "0");
        map.put("ask_ret_page", "0");
        map.put("ignore_update_pay_result", "0");
        WxPayFace.getInstance().getWxpayfaceCode(map, new IWxPayfaceCallback() {
            @Override
            public void response(Map info) throws RemoteException {
                Log.d("getWxpayfaceCode: " + info.toString());
                if (info == null) {
                    new RuntimeException("调用返回为空").printStackTrace();
                    return;
                }
                //用户退出了人脸识别
                if (info.get("return_code").equals(String.valueOf(EnumWxFacePayPublicErrorCode.EnumGetFaceCodeErrorCode.USER_CANCEL))) {

                }
                //用户选择扫码支付
                else if (info.get("return_code").equals(String.valueOf(EnumWxFacePayPublicErrorCode.EnumGetFaceCodeErrorCode.SCAN_PAYMENT))) {
                    startCodeScanner();
                }
                //人脸识别成功
                else if (info.get("return_code").equals(String.valueOf(EnumWxFacePayPublicErrorCode.SUCCESS))) {
                    String openid = info.get("openid").toString(); // openid
                    String faceCode = info.get("face_code").toString(); // 人脸凭证，用于刷脸支付
                    facePay(openid, faceCode, authInfoRsp.getOut_trade_no());
                }
            }
        });
    }

    @Override
    public void getWxpayfaceUserInfo(AuthInfoRsp authInfoRsp) {
        // 详细的参数配置表可见上方的“接口参数表”
        Map<String, String> map = new HashMap<String, String>();

        map.put("appid", authInfoRsp.getAppid());
        map.put("mch_id", authInfoRsp.getMch_id());
        map.put("store_id", authInfoRsp.getStore_id());
//        m1.put("sub_appid", "xxxxxxxxxxxxxx"); // 子商户公众账号ID(非服务商模式不填)
//        m1.put("sub_mch_id", "填您的子商户号"); // 子商户号(非服务商模式不填)
//        m1.put("store_id", "填您的门店编号"); // 门店编号，必填
        map.put("face_authtype", "FACEID-ONCE"); // 人脸识别模式， FACEID-ONCE`: 人脸识别(单次模式) FACEID-LOOP`: 人脸识别(循环模式), 必填
        map.put("authinfo", authInfoRsp.getAuth_info());
//        m1.put("ask_unionid", "1"); // 是否获取union_id    0：获取    1：不获取
        WxPayFace.getInstance().getWxpayfaceUserInfo(map, new IWxPayfaceCallback() {
            @Override
            public void response(Map info) throws RemoteException {
                Log.d("getWxpayfaceUserInfo:  " + info.toString());
                if (info == null) {
                    new RuntimeException("调用返回为空").printStackTrace();
                    return;
                }
                String code = (String) info.get("return_code"); // 错误码
                String msg = (String) info.get("return_msg"); // 错误码描述
                String openid = info.get("openid").toString(); // openid
                String sub_openid = "";
                if (info.get("sub_openid") != null) sub_openid = info.get("sub_openid").toString(); // 子商户号下的openid(服务商模式)
                String nickName = info.get("nickname").toString(); // 微信昵称
                if (code == null || openid == null || nickName == null || !code.equals("SUCCESS")) {
                    new RuntimeException("调用返回非成功信息,return_msg:" + msg + "   ").printStackTrace();
                    return ;
                }
                /*
                获取union_id逻辑，传入参数ask_unionid为"1"时使用
                String unionid_code = "";
                if (info.get("unionid_code") != null) unionid_code = info.get("unionid_code").toString();
                if (TextUtils.equals(unionid_code,"SUCCESS")) {
                    //获取union_id逻辑
                } else {
                    String unionid_msg = "";
                    if (info.get("unionid_msg") != null) unionid_msg = info.get("unionid_msg").toString();
                    //处理返回信息
                }
                */
       	        /*
       	        在这里处理您自己的业务逻辑
       	        需要注意的是：
       	            1、上述注释中的内容并非是一定会返回的，它们是否返回取决于相应的条件
       	            2、当您确保要解开上述注释的时候，请您做好空指针的判断，不建议直接调用
       	         */
            }
        });
    }

    @Override
    public void startCodeScanner() {

        currentStatus = CODE_SCANING;
        view.setCurrentStatus(HomeActivity.CODE_SCANING);
        WxPayFace.getInstance().startCodeScanner(new IWxPayfaceCallback() {
            @Override
            public void response(Map map) throws RemoteException {
                //异步线程
                Log.d("startCodeScanner:  " + map.toString());
                //扫码成功
                if (map.get("return_code").equals(String.valueOf(EnumWxFacePayPublicErrorCode.SUCCESS))) {
                    codePay(map.get("code_msg").toString());
                }
                //扫码失败
                else {
                }
            }
        });
    }

    @Override
    public void stopCodeScanner() {
        WxPayFace.getInstance().stopCodeScanner();
        view.setCurrentStatus(HomeActivity.IDLE);
    }

    @Override
    public void codePay(String payCode) {
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> emitter) throws Exception {
                emitter.onNext(payCode);
            }
        }).observeOn(AndroidSchedulers.mainThread())
                .map(new Function<String, RequestBase>() {
                    @Override
                    public RequestBase apply(String s) throws Exception {
                        //加载弹窗
                        view.isSshowWeChatLoadingDialog(true);
                        LoginRsp loginRsp = Hawk.get(SPKey.LOGIN_RSP);
                        int sotreId = loginRsp.getSid();
                        String nonceStr = RandomStringUtil.getRandomString(10);
                        Map<String, Object> map = new HashMap<>();
                        map.put("store_id", sotreId);
                        map.put("total", view.getTotalStr());
                        map.put("nonce_str", nonceStr);
                        map.put("authCode", payCode);
                        String dataAddSaleStr = buildRequestDataForSign(map, loginRsp.getKey());
                        String sign = MD5Utils.MD5Upper(dataAddSaleStr);
                        RequestBase requestBase = new RequestBase(loginRsp.getAppid(), Constants.AUTO_PAY, map, sign);
                        return requestBase;
                    }
                }).flatMap(new Function<RequestBase, Observable<BaseResponse<CodePayRsp>>>() {
            @Override
            public Observable<BaseResponse<CodePayRsp>> apply(RequestBase requestBase) throws Exception {
                return homeModel.codePay(requestBase);
            }
        }).subscribe(new BaseObserver<CodePayRsp>() {
            @Override
            protected void onSuccees(BaseResponse<CodePayRsp> t) throws Exception {
                view.isSshowWeChatLoadingDialog(false);
                view.facePayResult(true);
            }

            @Override
            protected void onCodeError(BaseResponse<CodePayRsp> t) throws Exception {
                view.isSshowWeChatLoadingDialog(false);
                view.facePayResult(false);
            }

            @Override
            protected void onFailure(String errorMsg, boolean isNetWorkError) throws Exception {
                view.isSshowWeChatLoadingDialog(false);
                view.facePayResult(false);
            }
        });
    }

    @Override
    public void openPhysicalKeyboard() {
        if (keyboard == null || keyboard.isReleased()) {
            keyboard = PayKeyboard.get(context);
            if (keyboard != null) {
                keyboard.setLayout(getKeyboardLayout());
                keyboard.setBaudRate(9600);
                keyboard.setListener(new DefaultKeyboardListener() {
                    @Override
                    public void onRelease() {
                        openPhysicalKeyboard();
                    }

                    @Override
                    public void onAvailable() {
                        openPhysicalKeyboard();
                    }

                    @Override
                    public void onException(Exception e) {
                        android.util.Log.i("KeyboardUI", "usb exception!!!!", e);
                        openPhysicalKeyboard();
                    }

                    @Override
                    public void onPay(final IPayRequest request) {
                    }

                    @Override
                    public void onKeyDown(final int keyCode, final String keyName) {
                        Log.d("keyCode:  " + keyCode + "  keyName:  " + keyName);
                        EventBus.getDefault().post(new EventKeyboardInfo(keyCode, keyName));
                    }

                    @Override
                    public void onKeyUp(int keyCode, String keyName) {

                    }
                });
                keyboard.open();
            } else {
                //ToastUtils.showShort("小键盘连接失败");
                Log.d("小键盘连接失败");
            }
        }

    }

    @Override
    public void realeasePhysicalKeyboard() {
        if (keyboard != null) {
            keyboard.release();
            keyboard = null;
        }
    }

    /**
     * 刷脸支付
     *
     * @param openId
     * @param faceCode
     * @param outTradeNo
     */
    private void facePay(String openId, String faceCode, String outTradeNo) {
        view.setCurrentStatus(HomeActivity.FACE_SCANING);
        LoginRsp loginRsp = Hawk.get(SPKey.LOGIN_RSP);
        int sotreId = loginRsp.getSid();
        String nonceStr = RandomStringUtil.getRandomString(10);
        Map<String, Object> map = new HashMap<>();
        map.put("store_id", sotreId);
        map.put("total", view.getTotalStr());
        map.put("openId", openId);
        map.put("faceCode", faceCode);
        map.put("out_trade_no", outTradeNo);
        map.put("nonce_str", nonceStr);
        String dataAddSaleStr = buildRequestDataForSign(map, loginRsp.getKey());
        String sign = MD5Utils.MD5Upper(dataAddSaleStr);
        RequestBase requestBase = new RequestBase(loginRsp.getAppid(), Constants.WX_FACEPAY, map, sign);
        homeModel.facePay(requestBase)
                .subscribe(new BaseObserver<FacePayRsp>() {

                    @Override
                    protected void onSuccees(BaseResponse<FacePayRsp> t) throws Exception {
                        updateWxpayfaceBannerState(true);
                    }

                    @Override
                    protected void onCodeError(BaseResponse<FacePayRsp> t) throws Exception {
                        updateWxpayfaceBannerState(false);
                    }

                    @Override
                    protected void onFailure(String errorMsg, boolean isNetWorkError) throws Exception {
                        updateWxpayfaceBannerState(false);
                    }
                });
    }

    /**
     * 运营位控制接口
     * <p>
     * 设置运营位状态:
     * 0:可展示运营图片
     * 1:不可展示运营图片
     */
    private void updateWxpayfaceBannerState(boolean isPaySuccess) {
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        map.put("banner_state", 1); // 设置运营位状态   0： 可展示运营图片   1： 不可展示运营图片 必填
        WxPayFace.getInstance().updateWxpayfaceBannerState(map, new IWxPayfaceCallback() {
            @Override
            public void response(Map info) throws RemoteException {
                if (info == null) {
                    new RuntimeException("调用返回为空").printStackTrace();
                    view.facePayResult(false);
                    return;
                }
                String code = (String) info.get("return_code"); // 错误码
                String msg = (String) info.get("return_msg"); // 错误码描述
                if (code == null || !code.equals("SUCCESS")) {
                    new RuntimeException("调用返回非成功信息,return_msg:" + msg + "   ").printStackTrace();
                    view.facePayResult(false);
                    return;
                }
                /*
                在这里处理您自己的业务逻辑：
                执行到这里说明用户已经确认支付结果且成功了，此时刷脸支付界面关闭，您可以在这里选择跳转到其它界面
                 */
                view.facePayResult(isPaySuccess);
            }
        });
    }

    /**
     * 获取金股键盘布局
     */
    private String getKeyboardLayout() {
        Map<String, String> keyboardMap = new HashMap<>();
        keyboardMap.put("9", "0");
        keyboardMap.put("31", "1");
        keyboardMap.put("15", "2");
        keyboardMap.put("14", "3");
        keyboardMap.put("2", "4");
        keyboardMap.put("1", "5");
        keyboardMap.put("16", "6");
        keyboardMap.put("5", "7");
        keyboardMap.put("4", "8");
        keyboardMap.put("3", "9");
        keyboardMap.put("19", ".");
        keyboardMap.put("13", "BACKSPACE");
        keyboardMap.put("12", "REFUND");
        keyboardMap.put("28", "AUDIT");
        keyboardMap.put("29", "SET");
        keyboardMap.put("30", "CLEAR");
        keyboardMap.put("20", "CANCEL");
        keyboardMap.put("21", "SCAN_CODE");
        keyboardMap.put("23", "SCAN_FACE");
        keyboardMap.put("8", "F1");
        keyboardMap.put("7", "F2");
        keyboardMap.put("6", "F3");
        StringBuffer stringBuffer = new StringBuffer();
        for (Map.Entry<String, String> entry : keyboardMap.entrySet()) {
            stringBuffer.append(entry.getKey()).append(":").append(entry.getValue()).append(",");
        }
        return stringBuffer.toString();
    }

    @Override
    public void initHeart() {
        heartService.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                openPhysicalKeyboard();
            }
        }, 0, 5, TimeUnit.SECONDS);
    }

    @Override
    public void displayKeyboard(String data) {
        if (keyboard != null) {
            keyboard.updateDisplay(data);
        }
    }

    @Override
    public void cancel() {
        Log.d("cancel: " + currentStatus);
        switch (currentStatus) {
            case CODE_SCANING:
                stopCodeScanner();
                break;
            case FACE_SCANING:
                break;
            default:
                break;
        }
    }
}
